/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.lundberg.podcasts.util;

import java.util.ArrayList;

import org.lundberg.podcasts.types.Channel;
import org.lundberg.podcasts.types.Item;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;


/**
 *  This class parses an XML podcast feed into a <code>Channel</code> and list of
 *  <code>Item</code>s.
 */

public class SAXChannelHandler extends DefaultHandler
{
    private StringBuffer accumulator;
    private boolean inImage = false;
    private boolean inItem = false;
    private Item item;
    private String newestItemPubDate;
    
    public Channel channel;
    public ArrayList<Item> items;


    public SAXChannelHandler(String url) {

    	channel = new Channel();
        channel.url = url;
    }

    @Override
	public void startDocument()
    {
        accumulator = new StringBuffer();
        items = new ArrayList<Item>();
    }

    // reset the accumulator
    @Override
	public void startElement(String uri, String localName, String name, Attributes attributes)
    {
        accumulator.setLength(0);

        if (localName.equals("image")) {

        	channel.imageURL = attributes.getValue("href");
        	inImage = true;
        }
        else if (localName.equals("item")) {
        	item = new Item();
            inItem = true;
        }
        else if (localName.equals("enclosure")) {

        	item.enclosureURL = attributes.getValue("url");
        	
        	// Get the length (in bytes) of the audio file.  We don't care too much
        	// about this, since it's overwritten when we actually download the file
        	try {
        		item.size = Integer.parseInt(attributes.getValue("length"));
        	}
        	catch (NumberFormatException e) {
        	}
        }
        else if (localName.equals("thumbnail")) {
        	
        	channel.imageURL = attributes.getValue("url");
        }

    }

    // get the characters (stuff between the open/close tags)
    @Override
	public void characters(char[] buffer, int start, int length)
    {
        accumulator.append(buffer, start, length);
    }

    @Override
	public void endElement(String uri, String localName, String name)
    {
        String value = accumulator.toString().trim();
        
        if (localName.equals("title")) {
        	
            if (inItem) {
            	item.title = value;
            }
            else {
            	channel.title = value;
            }
        }
        else if (localName.equals("guid")) {

        	item.guid = value;
        }
        else if (localName.equals("pubDate")) {

        	if (inItem) {
        		item.setPubDate(value);
        		if (newestItemPubDate == null) {
        			newestItemPubDate = item.getPubDate();
        		}
        	}
        	else {
        		channel.setPubDate(value);
        	}
        }
        else if (localName.equals("description")) {

            if (inItem) {
            	item.setDescription(value);
            }
        }
        else if (localName.equals("url")) {

            if (inImage && !inItem && value != null && value.length() > 0) {

            	channel.imageURL = value;
            }
        }
        else if (localName.equals("image")) {

            inImage = false;
        }
        // itunes:duration
        else if (localName.equals("duration")) {

        	item.setDuration(value);
        }
        else if (localName.equals("author")) {

        	channel.author = value;
        }
        else if (localName.equals("link") && inItem) {
        	
        	if (item.enclosureURL == null) {
        		item.enclosureURL = value;
        	}
        }
        else if (localName.equals("item")) {
        	
            items.add(item);
            inItem = false;
        }
    }
    
    
    @Override
	public void endDocument()
    {
    	// If the channel doesn't have a pubDate, use the most recent item
    	if (channel.getPubDate() == null) {
    		channel.setPubDate(newestItemPubDate);
    	}
    }
}